﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using SharpCmd.IO;
using SharpCmd.Windows.Forms.Progress;

namespace SharpCmd.Dialogs.PanelActions
{
    internal partial class CopyForm : ProgressForm
    {
        public CopyForm(CopyFormType type)
        {
            InitializeComponent();
            this.Icon = MainForm.Instance.Icon;
            this.ProgressBar = progressBarWithText1;
            this.CancelButton = buttonCancel;
            this.PauseButton = buttonPause;
            this.FileNameLabel = labelCurrentFile;
            this.Type = type;
            this.Title = type == CopyFormType.Copy ? "Copy" : "Move";
            this.Text = Title + " - SharpCmd";
            AttachHandlers();
        }

        public CopyFormType Type { get; set; }
        internal List<FSObjectInfo> Infos { get; set; }
        internal string TargetDirectory { get; set; }
        internal string SourceDirectory { get; set; }

        private void CopyForm_Load(object sender, EventArgs e)
        {
            if (Infos == null || TargetDirectory == null || SourceDirectory == null)
                throw new InvalidOperationException("CopyForm: Infos or TargetDirectory or SourceDirectory is null!");
        }

        private void CopyForm_Shown(object sender, EventArgs e)
        {
            this.labelCurrentFile.Text = "[Preparing to copy...]";
            bwPrepare.RunWorkerAsync();
        }

        #region copy worker
        protected override void DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            string target = TargetDirectory;
            foreach (var info in Infos)
            {
                HandlePause();
                if (Worker.CancellationPending)
                    return;
                if (info.Fake)
                    return;
                if (info.Type == FSObjectType.Directory)
                {
                    if (info.Action == FSObjectAction.Copy)
                    {
                        if (!Directory.Exists(GetTargetDirectoryName(info)))
                            Directory.CreateDirectory(GetTargetDirectoryName(info));
                    }
                    else if (info.Action == FSObjectAction.Delete)
                    {
                        try
                        {
                            Directory.Delete(info.FullName);
                        }
                        catch (UnauthorizedAccessException ex)
                        {
                            MessageBox.Show("Cannot delete " + info.FullName + " (" + ex.Message + ")");
                        }
                    }
                }
                ((BackgroundWorker)sender).ReportProgress(0, new ProgressInfo() { CurrentIndex = i++, CurrentItem = info.FullName });
                if (info.Type == FSObjectType.Directory)
                    continue;
                File.Copy(info.FullName, GetTargetName(info, target));
                if (Type == CopyFormType.Move)
                {
                    try
                    {
                        if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                            File.SetAttributes(info.FullName, FileAttributes.Normal);
                        File.Delete(info.FullName);
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        MessageBox.Show("Cannot delete " + info.FullName + " (" + ex.Message + ")");
                    }
                }
            }
        }

        private string GetTargetDirectoryName(FSObjectInfo info)
        {
            return GetTargetName(info, TargetDirectory);
        }

        private string GetTargetName(FSObjectInfo info, string targetDirectory)
        {
            string newRelativePath = info.FullName.Substring(SourceDirectory.Length).Trim('\\');
            return Path.Combine(targetDirectory, newRelativePath);
        }
        #endregion

        #region prepare
        private void bwPrepare_DoWork(object sender, DoWorkEventArgs e)
        {
            FSObjectAction action = this.Type == CopyFormType.Copy ? FSObjectAction.Copy : FSObjectAction.Move;
            Infos = FSObjectInfo.GetAllInfosRecursive(Infos, FSObjectAction.Copy | FSObjectAction.Delete); //adds copied & deleted dirs
            foreach (var inf in Infos)
            {
                System.Diagnostics.Trace.WriteLine(inf.FullName);
            }
        }

        private void bwPrepare_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressBarWithText1.Maximum = Infos.Count();
            Worker.RunWorkerAsync();
        }
        #endregion
    }
}